<!DOCTYPE html><html lang="zh-CN" data-theme="dark"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>小红书项目功能目录 | Albert Yuan's Blog</title><meta name="keywords" content="Swift"><meta name="author" content="Albert Yuan"><meta name="copyright" content="Albert Yuan"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#0d0d0d"><meta name="referrer" content="no-referrer"><meta name="description" content="1-仿小红书实战教程简介\1. 1-1简介-(使用技术+项目介绍+讲课方式+学习方法)   xib+code方式：    支持 不支持    社交类型模块 即时通讯，商城、直播模块   点赞，收藏，发布，评论，回复，登录 关注，附近，消息   深色模式、推送功能、coreData…     2-版本控制\2. 2-1用Xcode做项目的版本控制 \3. 2-2用Xcode进行代码的commit和p">
<meta property="og:type" content="article">
<meta property="og:title" content="小红书项目功能目录">
<meta property="og:url" content="https://yllove.gitee.io/2021/09/02/%E4%BB%BF%E5%B0%8F%E7%BA%A2%E4%B9%A6%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E5%B0%8F%E7%BA%A2%E4%B9%A6%E9%A1%B9%E7%9B%AE%E5%8A%9F%E8%83%BD%E7%9B%AE%E5%BD%95/index.html">
<meta property="og:site_name" content="Albert Yuan&#39;s Blog">
<meta property="og:description" content="1-仿小红书实战教程简介\1. 1-1简介-(使用技术+项目介绍+讲课方式+学习方法)   xib+code方式：    支持 不支持    社交类型模块 即时通讯，商城、直播模块   点赞，收藏，发布，评论，回复，登录 关注，附近，消息   深色模式、推送功能、coreData…     2-版本控制\2. 2-1用Xcode做项目的版本控制 \3. 2-2用Xcode进行代码的commit和p">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbpic.588ku.com%2Felement_origin_min_pic%2F18%2F03%2F22%2F4e2d28d716f1611ad997912eb463ffbe.jpg&refer=http%3A%2F%2Fbpic.588ku.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1633152676&t=2f3a092b8df4077187b137d42d5cda66">
<meta property="article:published_time" content="2021-09-02T05:29:55.077Z">
<meta property="article:modified_time" content="2021-09-08T02:06:41.358Z">
<meta property="article:author" content="Albert Yuan">
<meta property="article:tag" content="Swift">
<meta property="article:tag" content="Swift项目">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbpic.588ku.com%2Felement_origin_min_pic%2F18%2F03%2F22%2F4e2d28d716f1611ad997912eb463ffbe.jpg&refer=http%3A%2F%2Fbpic.588ku.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1633152676&t=2f3a092b8df4077187b137d42d5cda66"><link rel="shortcut icon" href="/blog/img/favicon.png"><link rel="canonical" href="https://yllove.gitee.io/2021/09/02/%E4%BB%BF%E5%B0%8F%E7%BA%A2%E4%B9%A6%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E5%B0%8F%E7%BA%A2%E4%B9%A6%E9%A1%B9%E7%9B%AE%E5%8A%9F%E8%83%BD%E7%9B%AE%E5%BD%95/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><meta/><link rel="stylesheet" href="/blog/css/index.css"><link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/instantsearch.js@2.10.5/dist/instantsearch.min.css" media="print" onload="this.media='all'"><script src="https://fastly.jsdelivr.net/npm/instantsearch.js@2.10.5/dist/instantsearch.min.js" defer></script><script>const GLOBAL_CONFIG = { 
  root: '/blog/',
  algolia: {"appId":"X8NS0XSX99","apiKey":"b9d4530647c8b5bf7928a04c47752ad7","indexName":"albertyuan","hits":{"per_page":6},"languages":{"input_placeholder":"搜索文章","hits_empty":"找不到您查询的内容：${query}","hits_stats":"找到 ${hits} 条结果，用时 ${time} 毫秒"}},
  localSearch: {"path":"search.xml","languages":{"hits_empty":"找不到您查询的内容：${query}"}},
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '天',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  source: {
    jQuery: 'https://fastly.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js',
    justifiedGallery: {
      js: 'https://fastly.jsdelivr.net/npm/justifiedGallery/dist/js/jquery.justifiedGallery.min.js',
      css: 'https://fastly.jsdelivr.net/npm/justifiedGallery/dist/css/justifiedGallery.min.css'
    },
    fancybox: {
      js: 'https://fastly.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js',
      css: 'https://fastly.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.css'
    }
  },
  isPhotoFigcaption: true,
  islazyload: true,
  isanchor: true
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: '小红书项目功能目录',
  isPost: true,
  isHome: false,
  isHighlightShrink: true,
  isToc: true,
  postUpdate: '2021-09-08 10:06:41'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const fontSizeVal = saveToLocal.get('global-font-size')
    if (fontSizeVal !== undefined) {
      document.documentElement.style.setProperty('--global-font-size', fontSizeVal + 'px')
    }
    
    const detectApple = () => {
      if (GLOBAL_CONFIG_SITE.isHome && /iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><meta name="generator" content="Hexo 6.2.0"><link rel="alternate" href="/blog/atom.xml" title="Albert Yuan's Blog" type="application/atom+xml">
</head><body><div id="loading-box"><div class="loading-left-bg"></div><div class="loading-right-bg"></div><div class="spinner-box"><div class="configure-border-1"><div class="configure-core"></div></div><div class="configure-border-2"><div class="configure-core"></div></div><div class="loading-word">加载中...</div></div></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src= "" data-lazy-src="/blog/img/favicon.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data"><div class="data-item is-center"><div class="data-item-link"><a href="/blog/archives/"><div class="headline">文章</div><div class="length-num">155</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/blog/tags/"><div class="headline">标签</div><div class="length-num">56</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/blog/categories/"><div class="headline">分类</div><div class="length-num">32</div></a></div></div></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/blog/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/blog/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/blog/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/blog/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/blog/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbpic.588ku.com%2Felement_origin_min_pic%2F18%2F03%2F22%2F4e2d28d716f1611ad997912eb463ffbe.jpg&amp;refer=http%3A%2F%2Fbpic.588ku.com&amp;app=2002&amp;size=f9999,10000&amp;q=a80&amp;n=0&amp;g=0n&amp;fmt=jpeg?sec=1633152676&amp;t=2f3a092b8df4077187b137d42d5cda66')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/blog/">Albert Yuan's Blog</a></span><div id="menus"><div id="search-button"><a class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/blog/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/blog/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/blog/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/blog/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/blog/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">小红书项目功能目录</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2021-09-02T05:29:55.077Z" title="发表于 2021-09-02 13:29:55">2021-09-02</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2021-09-08T02:06:41.358Z" title="更新于 2021-09-08 10:06:41">2021-09-08</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/blog/categories/Swift%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/">Swift项目实战</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">7.8k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>28分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="小红书项目功能目录"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h6 id="1-仿小红书实战教程简介"><a href="#1-仿小红书实战教程简介" class="headerlink" title="1-仿小红书实战教程简介"></a><strong>1-仿小红书实战教程简介</strong></h6><p>\1. 1-1简介-(使用技术+项目介绍+讲课方式+学习方法)  </p>
<p>xib+code方式：</p>
<table>
<thead>
<tr>
<th>支持</th>
<th>不支持</th>
</tr>
</thead>
<tbody><tr>
<td>社交类型模块</td>
<td>即时通讯，商城、直播模块</td>
</tr>
<tr>
<td>点赞，收藏，发布，评论，回复，登录</td>
<td>关注，附近，消息</td>
</tr>
<tr>
<td>深色模式、推送功能、coreData…</td>
<td></td>
</tr>
</tbody></table>
<hr>
<h6 id="2-版本控制"><a href="#2-版本控制" class="headerlink" title="2-版本控制"></a><strong>2-版本控制</strong></h6><p>\2. 2-1用Xcode做项目的版本控制</p>
<p>\3. 2-2用Xcode进行代码的commit和push</p>
<p>\4. 2-3用Git命令行工具做项目的版本控制</p>
<p>\5. 2-4给iOS项目做版本控制的两种方法的总结 </p>
<hr>
<h6 id="3-项目整体设计"><a href="#3-项目整体设计" class="headerlink" title="3-项目整体设计"></a><strong>3-项目整体设计</strong></h6><p>\6. 3-1TabBarController+TabBar+TabBarItem</p>
<p>\7. 3-2SFSymbols2+调整TabBarItem的顺序</p>
<p>\8. 3-3项目主题色-Tint+GlobalTint+ImageTint</p>
<p>\9. 3-4取色器+RGBColor+HexColor</p>
<p>\10. 3-5用一般图片做TabBarItem图标</p>
<p>\11. 3-6App图标设计+两个比较好用的设计网站 </p>
<p>\12. 3-7制作启动页图片+深色模式适配  </p>
<p>\13. 3-8制作启动页+深色模式适配利器SystemColor初探</p>
<p>\14. 3-9利用系统自带动态颜色自动适配深色模式</p>
<p>\15. 3-10图片的深色模式适配+强制深浅色模式</p>
<hr>
<h6 id="4-Cocoapods"><a href="#4-Cocoapods" class="headerlink" title="4-Cocoapods"></a><strong>4-Cocoapods</strong></h6><p>\16. 4-1可横滑的多Tab导航布局原理+XLPagerTabStrip</p>
<p>\17. 4-2cocoapods命令行工具+第三方库的索引包 </p>
<p>\18. 4-3Google搜索技巧+pod repo update </p>
<p>\19. 4-4podfile中的platform </p>
<p>\20. 4-5静态库和动态库+use_framework!</p>
<p>\21. 4-6podfile中第三方包的版本限制</p>
<p>\22. 4-7第三方包的版本锁定(Podfile.lock文件)</p>
<p>\23. 4-8’pod install’和’pod update’命令的区别</p>
<hr>
<h6 id="5-横滑Tab布局"><a href="#5-横滑Tab布局" class="headerlink" title="5-横滑Tab布局"></a><strong>5-横滑Tab布局</strong></h6><p>\24. 5-1XLPagerTabStrip+读懂第三方包的四种做法</p>
<p>\25. 5-2XLPagerTabStrip示例代码+继承第三方包里的类 </p>
<p>\26. 5-3连接Storyboard上的控件和第三方包里的outlet属性  </p>
<p>\27. 5-4配置子视图控制器+常量文件+配置barTitle</p>
<p>\28. 5-5UICollectionViewFlowLayout的属性+输入法小技巧 </p>
<p>\29. 5-6自定义Tab栏的UI+与第三方库的斗争</p>
<p>\30. 5-7创建代码片段+用闭包属性设置选中及非选中时UI  </p>
<p>\31. 5-8修改SB上的属性无效时用代码修改+产品逻辑的妥协  </p>
<p>\32. 5-9新版Storyboard做UI的高效性+可无视的红色约束错误  </p>
<hr>
<h6 id="6-瀑布流布局"><a href="#6-瀑布流布局" class="headerlink" title="6-瀑布流布局"></a><strong>6-瀑布流布局</strong></h6><p>\33. 6-1如何搜索不知道名字的功能+瀑布流布局初探 </p>
<p>\34. 6-2文档是OC代码时的解决方案+配置UICollectionviewController  </p>
<p>\35. 6-3Layout属性的初始赋值和随后改值+瀑布流布局的实现 </p>
<p>\36. 6-4自定义瀑布流UI+cell的渲染方向itemRenderDirection  </p>
<p>\37. 6-5上部Tab和瀑布流VC的联动(UIScrollView内嵌UICollectionview)</p>
<p>\38. 6-6复制粘贴何时无罪+学习主流包的必要性(开发项目的必经之路)</p>
<hr>
<h6 id="7-本地化和国际化"><a href="#7-本地化和国际化" class="headerlink" title="7-本地化和国际化"></a><strong>7-本地化和国际化</strong></h6><p>\39. 7-1本地化的目的+leading和trailing的自动适配</p>
<p>\40. 7-2本地化第一步添加语言(可使系统控件自动本地化)+本地化的时机</p>
<p>\41. 7-3Storyboard上的文本本地化+更新strings文件</p>
<p>\42. 7-4代码中文本的本地化-手动创建Localizable.strings</p>
<p>\43. 7-5代码中文本的本地化-批量提取文本进strings文件</p>
<p>\44. 7-6App名称的本地化+CFBundleDisplayName</p>
<p>\45. 7-7图片的本地化</p>
<hr>
<h6 id="8-选取照片和视频"><a href="#8-选取照片和视频" class="headerlink" title="8-选取照片和视频"></a><strong>8-选取照片和视频</strong></h6><p>\46. 8-1真机调试的常见错误+功能分析</p>
<p>\47. 8-2YPImagePicker+UITabBarController的delegate方法</p>
<p>\48. 8-3判断并区分VC的方法+申请照片和视频诸权限</p>
<p>\49. 8-4YPImagePicker的简单使用</p>
<p>\50. 8-5YPImagePicker通用配置-手势冲突+写入照片权限</p>
<p>\51. 8-6存照片的相簿名称+Bundle的两个字典属性</p>
<p>\52. 8-7扩展系统类Extension</p>
<p>\53. 8-8YPImagePicker通用配置-overlayView+遇到文档中坑的对策</p>
<p>\54. 8-9YPImagePicker相册配置(上)</p>
<p>\55. 8-10YPImagePicker相册配置(下)+画廊配置</p>
<p>\56. 8-11YPImagePicker视频配置</p>
<p>\57. 8-12YPImagePicker多选时的处理+取消事件+is的用法</p>
<hr>
<h5 id="9-Swift高级"><a href="#9-Swift高级" class="headerlink" title="9-Swift高级"></a><strong>9-Swift高级</strong></h5><p>\58. 9-1闭包的语法+闭包和函数的区别</p>
<p>\59. 9-2作为全局函数的闭包</p>
<p>\60. 9-3作为函数参数的闭包+传参时可用函数替代</p>
<p>\61. 9-4闭包的简写-尾随闭包TrailingClosure</p>
<p>\62. 9-5闭包的用途+传值机制</p>
<p>\63. 9-6作为Delegate方法的闭包(回调)+闭包简写-类型推断及省略参数</p>
<p>\64. 9-7闭包的应用-系统函数sorted</p>
<p>\65. 9-8闭包的捕获机制CapturingValues</p>
<p>\66. 9-9逃逸闭包Escaping-被存储在外层函数外面的变量中</p>
<p>\67. 9-10逃逸闭包Escaping-在异步耗时任务完成后执行的闭包需逃逸</p>
<p>\68. 9-11内存地址+值类型和引用类型简介</p>
<p>\69. 9-12深拷贝和浅拷贝</p>
<p>\70. 9-13iOS内存管理机制-ARC</p>
<p>\71. 9-14循环引用ReferenceCycle+内存泄露MemoryLeak</p>
<p>\72. 9-15弱引用weak+无主引用unowned</p>
<p>\73. 9-16其中一方非强引现象+delegate的弱引用</p>
<p>\74. 9-17作为全局函数的闭包捕获造成的循环引用</p>
<p>\75. 9-18逃逸闭包捕获造成的循环引用</p>
<p>\76. 9-19枚举的遍历+原始值</p>
<p>\77. 9-20枚举的关联值+值绑定(元祖的分解)</p>
<hr>
<h5 id="10-CollectionView"><a href="#10-CollectionView" class="headerlink" title="10-CollectionView"></a><strong>10-CollectionView</strong></h5><p>\78. 10-1编辑笔记页面需求分析</p>
<p>\79. 10-2UIScrollView-Bounce和ContentSize</p>
<p>\80. 10-3新版Xcode中AutoLayout的强制更改</p>
<p>\81. 10-4UICollectionView的EstimateSize</p>
<p> \82. 10-5UICollectionView基本操作+找不到对应代码文件的解决方案</p>
<p>\83. 10-6图片后缀名问题+UICollectionView配置数据</p>
<p>\84. 10-7两种设layer类型属性的方法+给SB面板添加属性@IBInspectable</p>
<p>\85. 10-8用代码做UICollectionView和AutoLayout</p>
<p>\86. 10-9注册cell+元类型(.Type和.self)</p>
<p>\87. 10-10用代码做UICollectionViewCell+视图层级的调试</p>
<p>\88. 10-11UICollectionView的SectionFooter</p>
<p>\89. 10-12用代码给UIButton添加点击事件和Border</p>
<p>\90. 10-13追加笔记照片(上)</p>
<p>\91. 10-14追加笔记照片(下)</p>
<p>\92. 10-15在Swift项目中使用OC写的库-桥接header文件</p>
<p>\93. 10-16提示框MBProgressHUD的使用及封装</p>
<p>\94. 10-17点击缩略图预览图片SKPhotoBrowser</p>
<p>\95. 10-18点击缩略图预览视频AVPlayerViewController</p>
<p>\96. 10-19Cell的拖拽UICollectionViewDragDelegate</p>
<p>\97. 10-20Cell的放下UICollectionViewDropDelegate-正在拖拽时</p>
<p>\98. 10-21Cell的放下UICollectionViewDropDelegate-手指离开屏幕时</p>
<hr>
<h5 id="11-UITextField"><a href="#11-UITextField" class="headerlink" title="11-UITextField"></a><strong>11-UITextField</strong></h5><p>\99. 11-1UITextField需求分析+UI布局</p>
<p>\100. 11-2UITextField聚焦和失去焦点时的事件Action</p>
<p>\101. 11-3滑动ScrollView时收起软键盘keyboardDismissMode</p>
<p>\102. 11-4轻触return键收起软键盘editingDidEndOnExit</p>
<p>\103. 11-5点击空白处收起软键盘cancelsTouchesInView</p>
<p>\104. 11-6实时显示剩余可输字符editingChanged</p>
<p>\105. 11-7字符超限后不可输入shouldChangeCharactersIn-range</p>
<p>\106. 11-8字符超限后不可输入-粘贴文本时的处理</p>
<p>\107. 11-9压缩优先级和拉伸优先级的实际使用</p>
<p>\108. 11-10UITextView的内边距和缩进</p>
<p>\109. 11-11给UITextView加placeholder+内边距调整</p>
<p>\110. 11-12用系统自带拼音键盘输入汉字时的bug处理</p>
<p>\111. 11-13UITextView的行间距和行高+typingAttributes</p>
<p>\112. 11-14修改用户输入文本的属性+光标颜色</p>
<p>\113. 11-15在软键盘上面加工具栏inputAccessoryView+加载xib上的view</p>
<p>\114. 11-16inputAccessoryView的完成按钮+布局设计</p>
<p>\115. 11-17UITextView的字数统计+didset实战</p>
<p>\116. 11-18扩展静态方法+泛型</p>
<hr>
<h5 id="12-参与话题功能"><a href="#12-参与话题功能" class="headerlink" title="12-参与话题功能"></a><strong>12-参与话题功能</strong></h5><p>\117. 12-1参与话题功能UI</p>
<p>\118. 12-2需求分析+Stackview技巧+添加手势并跳转页面</p>
<p>\119. 12-3话题页+UITableView</p>
<p>\120. 12-4父子视图控制器+dismiss的本质+反向传值</p>
<p>\121. 12-5接受数据后的处理+文档注释</p>
<hr>
<h5 id="13-高德地图SDK"><a href="#13-高德地图SDK" class="headerlink" title="13-高德地图SDK"></a><strong>13-高德地图SDK</strong></h5><p>\122. 13-1添加地点功能UI</p>
<p>\123. 13-2认识SDK+创建应用</p>
<p>\124. 13-3注册收费开发者账号时的坑</p>
<p>\125. 13-4安装高德定位SDK+IDFA广告标识符</p>
<p>\126. 13-5配置Key+请求定位的一些准备操作</p>
<p>\127. 13-6申请位置权限+逆地理编码</p>
<p>\128. 13-7LocationManager的强引用+POI和AOI</p>
<p>\129. 13-8不同地点下的逆地理信息+拼接当前位置信息</p>
<p>\130. 13-9POI页面的数据结构+UI</p>
<p>\131. 13-10配置cell数据+获取网络数据时的处理</p>
<p>\132. 13-11小菊花加载框</p>
<p>\133. 13-12搜索周边POI-AMapSearchAPI+AMapPOIAroundSearchRequest</p>
<p>\134. 13-13发起周边搜索请求+在delegate回调中接收数据</p>
<p>\135. 13-14扩展可选型类+代码优化+SDK的demo</p>
<p>\136. 13-15搜索请求的属性+实时关键字搜索POI</p>
<p>\137. 13-16实时搜索网络数据的局限性</p>
<p>\138. 13-17手动关键字搜索POI+清空搜索栏后的处理</p>
<p>\139. 13-18搜索周边POI上拉加载+MJRefresh</p>
<p>\140. 13-19当前页数+总页数</p>
<p>\141. 13-20全部加载完的处理</p>
<p>\142. 13-21关键字搜索POI上拉加载</p>
<p>\143. 13-22周边搜索和关键字搜索的联动-重置处理</p>
<p>\144. 13-23选择POI后反向传回笔记编辑页面</p>
<p>\145. 13-24POI正向传值+特殊POICell反向传回时的处理</p>
<p>\146. 13-25SearchBar自带取消按钮一开始无效的处理</p>
<p>\147. 13-26本章bug修复-随时更新(目前无内容可跳过)</p>
<hr>
<h5 id="14-本地存储CoreData"><a href="#14-本地存储CoreData" class="headerlink" title="14-本地存储CoreData"></a><strong>14-本地存储CoreData</strong></h5><p>\148. 14-1存为草稿和发布笔记的UI</p>
<p>\149. 14-2需求分析+CoreData自带代码分析</p>
<p>\150. 14-3Entity和Attribute+单例模式</p>
<p>\151. 14-4用面向对象方式存数据</p>
<p>\152. 14-5沙盒中的文件夹们</p>
<p>\153. 14-6sqlite数据库文件+获取文件路径及URL的方法+下载真机沙盒</p>
<p>\154. 14-7二进制大文件的存储ExternalStorage+增删字段时的自动迁移</p>
<p>\155. 14-8改字段类型时的简单迁移</p>
<p>\156. 14-9轻量迁移</p>
<p>\157. 14-10存图片和视频+压缩图片</p>
<p>\158. 14-11草稿cell的UI</p>
<p>\159. 14-12配置草稿cell+重命名数据库字段导致的迁移bug</p>
<p>\160. 14-13便利构造器的实际使用</p>
<p>\161. 14-14子类中的初始化构造器</p>
<p>\162. 14-15日期和时间DateTools(上)</p>
<p>\163. 14-16日期和时间DateTools(下)</p>
<p>\164. 14-17取出所有数据</p>
<p>\165. 14-18分页+筛选+排序</p>
<p>\166. 14-19懒加载Fault机制</p>
<p>\167. 14-20配置草稿页的瀑布流</p>
<p>\168. 14-21Alert弹框+删除草稿</p>
<p>\169. 14-22改草稿业务逻辑分析+JSON解码+高阶函数Map</p>
<p>\170. 14-23data转URL(上)-指定文件夹URL并创建文件夹</p>
<p>\171. 14-24data转URL(下)-指定文件URL并创建文件</p>
<p>\172. 14-25传图片和视频进编辑草稿页面</p>
<p>\173. 14-26用户若删除全部图片后的处理</p>
<p>\174. 14-27传除图片视频之外的数据进编辑草稿页+更新UI</p>
<p>\175. 14-28更新草稿+代码重构</p>
<p>\176. 14-29闭包属性的实际应用</p>
<p>\177. 14-30NavigationBar和NavigationItem</p>
<p>\178. 14-31GCD多线程+同步和异步+串行和并发</p>
<p>\179. 14-32串行队列同步执行+并发队列异步执行</p>
<p>\180. 14-33主队列和全局并发队列</p>
<p>\181. 14-34全局并发队列的实际应用</p>
<p>\182. 14-35在后台线程执行本地存储的增删改查(上)</p>
<p>\183. 14-36在后台线程执行本地存储的增删改查(下)</p>
<p>\184. 14-37传图片进笔记编辑页</p>
<p>\185. 14-38拍摄视频进笔记编辑页+生成视频封面(了解)</p>
<p>\186. 14-39本章bug修复-随时更新(2021.1.11更)</p>
<hr>
<h5 id="15-本机号码一键登录"><a href="#15-本机号码一键登录" class="headerlink" title="15-本机号码一键登录"></a><strong>15-本机号码一键登录</strong></h5><p>\187. 15-1网络应用的登录功能</p>
<p>Lebus59次播放</p>
<p>\188. 15-2本机号码一键登录的整体流程</p>
<p>Lebus29次播放</p>
<p>\189. 15-3极光SDK+公钥和私钥</p>
<p>Lebus32次播放</p>
<p>\190. 15-4登录逻辑+用代码制作按钮</p>
<p>Lebus30次播放</p>
<p>\191. 15-5集成极光认证SDK+配置并初始化一键登录服务</p>
<p>Lebus34次播放</p>
<p>\192. 15-6预取号-判断网络环境是否可一键登录</p>
<p>Lebus29次播放</p>
<p>\193. 15-7[2021.4.4更]获取一键登录token</p>
<p>Lebus22次播放</p>
<p>\194. 15-8一键登录流程回顾+配置自定义UI</p>
<p>Lebus25次播放</p>
<p>\195. 15-9自定义状态栏+导航栏+logo</p>
<p>Lebus21次播放</p>
<p>\196. 15-10自定义手机号码栏+slogan+一键登录按钮</p>
<p>Lebus18次播放</p>
<p>\197. 15-11自定义勾选框+用户协议栏</p>
<p>Lebus15次播放</p>
<p>\198. 15-12处理用户协议栏的约束+点击跳转后的页面</p>
<p>Lebus18次播放</p>
<p>\199. 15-13在授权页添加自定义View</p>
<p>Lebus18次播放</p>
<p>\200. 15-14UI收尾工作+代码重构</p>
<p>Lebus13次播放</p>
<p>\201. 15-15跳转至手机验证码登录页-present方式</p>
<p>Lebus15次播放</p>
<p>\202. 15-16跳转至手机验证码登录页-push方式(了解)</p>
<p>Lebus19次播放</p>
<p>\203. 15-17携带loginToken换取手机号并用私钥解密-终端请求方式</p>
<p>Lebus19次播放</p>
<p>\204. 15-18携带loginToken换取手机号-Postman请求方式</p>
<p>Lebus14次播放</p>
<p>\205. 15-19用Alamofire发送带有请求头和请求体的网络请求</p>
<p>Lebus20次播放</p>
<p>\206. 15-20把JSON类型的数据解码为Swift支持的类型</p>
<p>Lebus18次播放</p>
<hr>
<h5 id="16-支付宝登录"><a href="#16-支付宝登录" class="headerlink" title="16-支付宝登录"></a><strong>16-支付宝登录</strong></h5><p>\207. 16-1登录页面UI-导航栏</p>
<p>Lebus24次播放</p>
<p>\208. 16-2登录页面UI-复用view的三种方式+输入框</p>
<p>Lebus13次播放</p>
<p>\209. 16-3登录页面UI-Constrain to margins</p>
<p>Lebus15次播放</p>
<p>\210. 16-4登录页面UI-ContainerView和登录按钮</p>
<p>Lebus19次播放</p>
<p>\211. 16-5登录页面UI-第三方登录</p>
<p>Lebus18次播放</p>
<p>\212. 16-6在支付宝开放平台创建应用+配置公钥+添加能力</p>
<p>Lebus15次播放</p>
<p>\213. 16-7基本授权Basic和开放授权OAuth</p>
<p>Lebus14次播放</p>
<p>\214. 16-8运行Demo+沙箱环境</p>
<p>Lebus13次播放</p>
<p>\215. 16-9登录请求的第一个参数-拼接授权信息</p>
<p>Lebus9次播放</p>
<p>\216. 16-10登录请求的第一个参数-加签授权信息</p>
<p>Lebus7次播放</p>
<p>\217. 16-11登录请求的第二个参数-App间的跳转URLSchemes</p>
<p>Lebus7次播放</p>
<p>\218. 16-12登录请求+从别的App跳转回来时的回调</p>
<p>Lebus8次播放</p>
<p>\219. 16-13从响应结果中解析出authCode</p>
<p>Lebus6次播放</p>
<p>\220. 16-14用authCode换accessToken-信息类参数</p>
<p>Lebus6次播放</p>
<p>\221. 16-15用authCode换accessToken-签名参数</p>
<p>Lebus4次播放</p>
<p>\222. 16-16accessToken和refreshToken</p>
<p>Lebus3次播放</p>
<p>\223. 16-17用accessToken换取用户的个人信息</p>
<p>Lebus7次播放</p>
<p>\224. 16-18代码重构+支付宝SDK在线调试</p>
<p>Lebus2次播放</p>
<hr>
<h5 id="17-苹果登录"><a href="#17-苹果登录" class="headerlink" title="17-苹果登录"></a><strong>17-苹果登录</strong></h5><p>\225. 17-1UI+官方素材中的图片内边距</p>
<p>Lebus18次播放</p>
<p>\226. 17-2signInWithApple流程+BundleID被占用时的处理</p>
<p>Lebus19次播放</p>
<p>\227. 17-3苹果认证服务框架提供的两种登录方式+授权请求</p>
<p>Lebus14次播放</p>
<p>\228. 17-4授权成功后的回调+获取用户信息</p>
<p>Lebus6次播放</p>
<p>\229. 17-5identityToken和JWT</p>
<p>Lebus5次播放</p>
<p>\230. 17-6非首次登录时从本地取出用户信息</p>
<p>Lebus5次播放</p>
<p>\231. 17-7知识拾遗+获取苹果登录状态</p>
<p>Lebus6次播放</p>
<hr>
<h5 id="18-手机验证码登录"><a href="#18-手机验证码登录" class="headerlink" title="18-手机验证码登录"></a><strong>18-手机验证码登录</strong></h5><p>\232. 18-1后端云服务SDK-LeanCloud</p>
<p>Lebus37次播放</p>
<p>\233. 18-2上线前对LeanCloud的配置-备案域名</p>
<p>Lebus25次播放</p>
<p>\234. 18-3上线前对LeanCloud的配置-独立IP和域名解析</p>
<p>Lebus24次播放</p>
<p>\235. 18-4UI整体配置</p>
<p>Lebus19次播放</p>
<p>\236. 18-5正则表达式</p>
<p>Lebus11次播放</p>
<p>\237. 18-6验证用户输入的手机号码</p>
<p>Lebus15次播放</p>
<p>\238. 18-7限制手机号码和验证码输入位数</p>
<p>Lebus10次播放</p>
<p>\239. 18-8获取验证码后的倒计时-Timer</p>
<p>Lebus9次播放</p>
<p>\240. 18-9自定义的UIButton+获取验证码按钮的隐藏时机</p>
<p>Lebus9次播放</p>
<p>\241. 18-10验证用户输入的验证码+软键盘returnKey的处理</p>
<p>Lebus7次播放</p>
<p>\242. 18-11发送验证码短信-配置短信签名</p>
<p>Lebus18次播放</p>
<p>\243. 18-12发送验证码短信-配置短信模板并发送请求</p>
<p>Lebus12次播放</p>
<p>\244. 18-13发送验证码短信-启用服务和短信费用</p>
<p>Lebus11次播放</p>
<p>\245. 18-14配置短信模板时的注意点+发送验证码短信实测</p>
<p>Lebus10次播放</p>
<p>\246. 18-15登录+云端数据库中的User表</p>
<p>Lebus17次播放</p>
<p>\247. 18-16随机昵称+非关系型数据库NoSQL</p>
<p>Lebus17次播放</p>
<p>\248. 18-17上传图片进云端</p>
<p>Lebus19次播放</p>
<p>\249. 18-18把图片关联到LCFile类型的字段</p>
<p>Lebus9次播放</p>
<p>\250. 18-19封装存大文件的方法+在LC后台设置默认字段</p>
<p>Lebus7次播放</p>
<p>\251. 18-20在LC控制台配置苹果登录</p>
<p>Lebus6次播放</p>
<p>\252. 18-21在父视图中展示提示框+完成苹果登录</p>
<p>Lebus6次播放</p>
<p>\253. 18-22账号绑定+首次登录+利用LC可完成哪些登录功能</p>
<p>Lebus15次播放</p>
<hr>
<h5 id="19-登录和退出登录"><a href="#19-登录和退出登录" class="headerlink" title="19-登录和退出登录"></a><strong>19-登录和退出登录</strong></h5><p>\254. 19-1判断用户是否已登录</p>
<p>Lebus20次播放</p>
<p>\255. 19-2根据用户是否已登录展示个人页或登录按钮页</p>
<p>Lebus12次播放</p>
<p>\256. 19-3退出登录后展示登录按钮页</p>
<p>Lebus8次播放</p>
<p>\257. 19-4登录后展示个人页</p>
<p>Lebus11次播放</p>
<p>\258. 19-5判断当前是否在模拟器上运行#if和#else</p>
<p>Lebus9次播放</p>
<p>\259. 19-6代码优化+为什么需要网络任务伪同步执行</p>
<p>Lebus10次播放</p>
<p>\260. 19-7调度组DispatchGroup</p>
<p>Lebus12次播放</p>
<p>\261. 19-8调度组DispatchGroup实操</p>
<p>Lebus7次播放</p>
<hr>
<h5 id="20-发布笔记至云端"><a href="#20-发布笔记至云端" class="headerlink" title="20-发布笔记至云端"></a><strong>20-发布笔记至云端</strong></h5><p>\262. 20-1UIBarButtonItem+系统图标的配置</p>
<p>Lebus13次播放</p>
<p>\263. 20-2popup提示弹框</p>
<p>Lebus8次播放</p>
<p>\264. 20-3存储普通数据进云端</p>
<p>Lebus13次播放</p>
<p>\265. 20-4存储单个图片和视频进云端</p>
<p>Lebus15次播放</p>
<p>\266. 20-5存储所有图片进云端</p>
<p>Lebus14次播放</p>
<p>\267. 20-6排序图片的URL地址并存进云端</p>
<p>Lebus7次播放</p>
<p>\268. 20-7发布草稿笔记进云端</p>
<p>Lebus9次播放</p>
<hr>
<h5 id="21-笔记详情页UI"><a href="#21-笔记详情页UI" class="headerlink" title="21-笔记详情页UI"></a><strong>21-笔记详情页UI</strong></h5><p>\269. 21-1笔记详情页UI分析+上部bar</p>
<p>Lebus25次播放</p>
<p>\270. 21-2自定义可复用并可在IB上实时显示的Button-IBDesignable(上)</p>
<p>Lebus17次播放</p>
<p>\271. 21-3自定义可复用并可在IB上实时显示的Button-IBDesignable(下)</p>
<p>Lebus12次播放</p>
<p>\272. 21-4点赞+收藏+评论按钮</p>
<p>Lebus18次播放</p>
<p>\273. 21-5UI布局微调</p>
<p>Lebus12次播放</p>
<p>\274. 21-6笔记内容整体UI</p>
<p>Lebus36次播放</p>
<p>\275. 21-7UIButton的内边距+StackView中元素的宽高</p>
<p>Lebus17次播放</p>
<p>\276. 21-8图片预览+用代码修改约束</p>
<p>Lebus23次播放</p>
<p>\277. 21-9tableHeaderView的高度自适应+viewDidLayoutSubviews</p>
<p>Lebus16次播放</p>
<hr>
<h5 id="22-从云端取出笔记"><a href="#22-从云端取出笔记" class="headerlink" title="22-从云端取出笔记"></a><strong>22-从云端取出笔记</strong></h5><p>\278. 22-1首页UI</p>
<p>Lebus20次播放</p>
<p>\279. 22-2配置首页数据</p>
<p>Lebus21次播放</p>
<p>\280. 22-3从云端取出指定数据-条件查询</p>
<p>Lebus15次播放</p>
<p>\281. 22-4添加封面图宽高比字段+设定瀑布流Cell的宽高</p>
<p>Lebus14次播放</p>
<p>\282. 22-5一对多模型设计+关系查询</p>
<p>Lebus9次播放</p>
<p>\283. 22-6取出封面图和作者头像的URL</p>
<p>Lebus10次播放</p>
<p>\284. 22-7下载并缓存网络图片-Kingfisher</p>
<p>Lebus10次播放</p>
<p>\285. 22-8依赖注入-用一个对象构造另一个对象</p>
<p>Lebus11次播放</p>
<p>\286. 22-9取出笔记作者的头像和昵称</p>
<p>Lebus6次播放</p>
<p>\287. 22-10取出笔记的标题和正文及话题</p>
<p>Lebus6次播放</p>
<p>\288. 22-11取出日期+LC后台的数据库迁移</p>
<p>Lebus9次播放</p>
<p>\289. 22-12取出点赞收藏评论数+数字的格式化(上)</p>
<p>Lebus8次播放</p>
<p>\290. 22-13取出点赞收藏评论数+数字的格式化(下)</p>
<p>Lebus5次播放</p>
<p>\291. 22-14设置图片的高度约束+imageView的contentMode</p>
<p>Lebus9次播放</p>
<p>\292. 22-15取出图片+解决第一次加载时的白屏</p>
<p>Lebus11次播放</p>
<p>\293. 22-16把文件关联到字段的本质</p>
<p>Lebus9次播放</p>
<hr>
<h5 id="23-点赞和收藏"><a href="#23-点赞和收藏" class="headerlink" title="23-点赞和收藏"></a><strong>23-点赞和收藏</strong></h5><p>\294. 23-1多对多模型设计-中间表</p>
<p>Lebus10次播放</p>
<p>\295. 23-2点赞收藏功能分析+收集点赞收藏数据的目的</p>
<p>Lebus6次播放</p>
<p>\296. 23-3UIButton的isSelected属性</p>
<p>Lebus5次播放</p>
<p>\297. 23-4点赞和取消点赞时中间表的数据处理</p>
<p>Lebus4次播放</p>
<p>\298. 23-5在数据库增减笔记和作者的点赞数-原子操作</p>
<p>Lebus7次播放</p>
<p>\299. 23-6用户对象的安全-用户只能修改自己的User对象</p>
<p>Lebus4次播放</p>
<p>\300. 23-7首页点赞-设置按钮选中时的图片并手动切换isSelected属性</p>
<p>Lebus6次播放</p>
<p>\301. 23-8首页点赞-awakeFromNib和按钮图标的renderingMode</p>
<p>Lebus4次播放</p>
<p>\302. 23-9利用首页传值判断详情页的当前用户是否点赞</p>
<p>Lebus5次播放</p>
<p>\303. 23-10首页点赞去重</p>
<p>Lebus6次播放</p>
<p>\304. 23-11点赞优化-防暴力点击</p>
<p>Lebus9次播放</p>
<p>\305. 23-12点赞优化-暴力点击时间内仅奇数点击生效</p>
<p>Lebus7次播放</p>
<p>\306. 23-13笔记详情页的点赞优化</p>
<p>Lebus8次播放</p>
<p>\307. 23-14笔记详情页的收藏功能</p>
<p>Lebus5次播放</p>
<hr>
<h5 id="24-笔记的删除和编辑"><a href="#24-笔记的删除和编辑" class="headerlink" title="24-笔记的删除和编辑"></a><strong>24-笔记的删除和编辑</strong></h5><p>\308. 24-1用户看自己笔记时的UI</p>
<p>Lebus18次播放</p>
<p>\309. 24-2删除和编辑的UI+删除云端笔记</p>
<p>Lebus15次播放</p>
<p>\310. 24-3删除笔记后的UI处理</p>
<p>Lebus10次播放</p>
<p>\311. 24-4封装确认删除弹框功能</p>
<p>Lebus11次播放</p>
<p>\312. 24-5Kingfisher的缓存机制</p>
<p>Lebus17次播放</p>
<p>\313. 24-6从缓存中获取当前笔记的UIImage类型的图片</p>
<p>Lebus10次播放</p>
<p>\314. 24-7把笔记图片和笔记内容传入笔记编辑页面</p>
<p>Lebus7次播放</p>
<p>\315. 24-8更新笔记</p>
<p>Lebus9次播放</p>
<p>\316. 24-9更新笔记后详情页的数据和UI的处理(上)</p>
<p>Lebus7次播放</p>
<p>\317. 24-10更新笔记后详情页的数据和UI的处理(下)</p>
<p>Lebus6次播放</p>
<hr>
<h5 id="25-笔记的评论"><a href="#25-笔记的评论" class="headerlink" title="25-笔记的评论"></a><strong>25-笔记的评论</strong></h5><p>\318. 25-1发送评论UI分析+发送评论按钮</p>
<p>Lebus28次播放</p>
<p>\319. 25-2评论输入框-高度自增长的textView</p>
<p>Lebus14次播放</p>
<p>\320. 25-3UIScrollView及子类的软键盘适配</p>
<p>Lebus12次播放</p>
<p>\321. 25-4添加观察者以对软键盘弹起和收起进行监听+监听函数的参数</p>
<p>Lebus15次播放</p>
<p>\322. 25-5改变评论输入bar的底部约束+约束中的item顺序</p>
<p>Lebus15次播放</p>
<p>\323. 25-6软键盘的当前高度+弹出和收起评论输入bar时的动画</p>
<p>Lebus12次播放</p>
<p>\324. 25-7添加黑色透明遮罩</p>
<p>Lebus18次播放</p>
<p>\325. 25-8UI和代码优化</p>
<p>Lebus9次播放</p>
<p>\326. 25-9把评论存入云端</p>
<p>Lebus15次播放</p>
<p>\327. 25-10使用多段tableView做评论区+每段的header用来显示评论</p>
<p>Lebus20次播放</p>
<p>\328. 25-11配置sectionHeader+可重用view的contentView</p>
<p>Lebus18次播放</p>
<p>\329. 25-12评论UI+sectionHeader的高度自适应</p>
<p>Lebus10次播放</p>
<p>\330. 25-13配置评论数据源</p>
<p>Lebus10次播放</p>
<p>\331. 25-14把评论内容和评论时间各自转化为富文本并拼接(上)</p>
<p>Lebus9次播放</p>
<p>\332. 25-15把评论内容和评论时间各自转化为富文本并拼接(下)</p>
<p>Lebus10次播放</p>
<p>\333. 25-16云端时间类数据的注意点+评论时间</p>
<p>Lebus8次播放</p>
<p>\334. 25-17发布评论后的UI处理</p>
<p>Lebus18次播放</p>
<p>\335. 25-18作者标签+评论数</p>
<p>Lebus14次播放</p>
<p>\336. 25-19获取云端指定字段的数据-selected</p>
<p>Lebus11次播放</p>
<p>\337. 25-20从云端取出笔记的评论</p>
<p>Lebus7次播放</p>
<p>\338. 25-21#selector的简单传值</p>
<p>Lebus13次播放</p>
<p>\339. 25-22用KVC改变UIAlertAction的字体颜色</p>
<p>Lebus12次播放</p>
<p>\340. 25-23复制和删除评论(上)</p>
<p>Lebus12次播放</p>
<p>\341. 25-24复制和删除评论(下)</p>
<p>Lebus9次播放</p>
<hr>
<h5 id="26-笔记评论的回复"><a href="#26-笔记评论的回复" class="headerlink" title="26-笔记评论的回复"></a><strong>26-笔记评论的回复</strong></h5><p>\342. 26-1展示回复输入框+回复评论人的placeholder</p>
<p>Lebus16次播放</p>
<p>\343. 26-2判断用户发送的是评论还是回复的flag+reset处理</p>
<p>Lebus12次播放</p>
<p>\344. 26-3代码优化+存回复内容及回复人进回复表</p>
<p>Lebus11次播放</p>
<p>\345. 26-4存被回复的评论进回复表+tableView插入数据和删除数据的区别</p>
<p>Lebus17次播放</p>
<p>\346. 26-5回复cell的UI</p>
<p>Lebus12次播放</p>
<p>\347. 26-6在每段最后添加分隔线-tableView的sectionFooter</p>
<p>Lebus16次播放</p>
<p>\348. 26-7回复数据设计+从云端取出每个评论下的回复</p>
<p>Lebus15次播放</p>
<p>\349. 26-8把回复数据的外层数组排序以对应评论数组(上)</p>
<p>Lebus13次播放</p>
<p>\350. 26-9把回复数据的外层数组排序以对应评论数组(下)</p>
<p>Lebus11次播放</p>
<p>\351. 26-10配置回复数据源</p>
<p>Lebus8次播放</p>
<p>\352. 26-11回复cell的作者标签+发布回复后的内存数据处理</p>
<p>Lebus8次播放</p>
<p>\353. 26-12发布回复后的UI处理</p>
<p>Lebus8次播放</p>
<p>\354. 26-13超过一条回复时折叠回复并显示展开回复按钮</p>
<p>Lebus9次播放</p>
<p>\355. 26-14展开回复按钮的文本+把每段的回复数组变成对象</p>
<p>Lebus10次播放</p>
<p>\356. 26-15点开按钮前后显示不同的行数-自定义对象的flag属性</p>
<p>Lebus12次播放</p>
<p>\357. 26-16点开按钮后按钮的隐藏+细节处理</p>
<p>Lebus7次播放</p>
<p>\358. 26-17点击自己发布的回复cell后的UI</p>
<p>Lebus9次播放</p>
<p>\359. 26-18删除回复+代码优化</p>
<p>Lebus7次播放</p>
<p>\360. 26-19UITableViewCell重用机制-需穷举配置数据</p>
<p>Lebus8次播放</p>
<p>\361. 26-20回复一个回复-子回复</p>
<p>Lebus9次播放</p>
<p>\362. 26-21代码重构+reset处理</p>
<p>Lebus5次播放</p>
<p>\363. 26-22子回复时的UI-回复谁谁</p>
<p>Lebus7次播放</p>
<p>\364. 26-23云端查询优化-评论表中加一个是否有回复字段</p>
<p>Lebus9次播放</p>
<p>\365. 26-24云端查询优化-仅在这个评论有回复时才查询</p>
<p>Lebus8次播放</p>
<p>\366. 26-25云端查询优化-回复被删光时的重置</p>
<p>Lebus7次播放</p>
<hr>
<h5 id="27-笔记详情页的优化及bug处理"><a href="#27-笔记详情页的优化及bug处理" class="headerlink" title="27-笔记详情页的优化及bug处理"></a><strong>27-笔记详情页的优化及bug处理</strong></h5><p>\367. 27-1约束的冲突</p>
<p>Lebus8次播放</p>
<p>\368. 27-2点赞收藏bug处理</p>
<p>Lebus7次播放</p>
<p>\369. 27-3在回复折叠状态下回复的bug处理</p>
<p>Lebus7次播放</p>
<p>\370. 27-4tableView的那些header和footer</p>
<p>Lebus5次播放</p>
<p>\371. 27-5收藏去重</p>
<p>Lebus5次播放</p>
<hr>
<h5 id="28-个人页面"><a href="#28-个人页面" class="headerlink" title="28-个人页面"></a><strong>28-个人页面</strong></h5><p>\372. 28-1整体UI分析</p>
<p>\373. 28-2嵌套的scrollView-SegementSlide</p>
<p>\374. 28-3重写和覆盖父类属性</p>
<p>\375. 28-4个人信息view布局分析+上部按钮</p>
<p>\376. 28-5用户头像+昵称+个人简介UI</p>
<p>\377. 28-6社交信息UI+胶囊按钮</p>
<p>\378. 28-7UIScrollView的alwaysBounceVertical</p>
<p>\379. 28-8个人信息view的高度+上滑折叠小bug</p>
<p>\380. 28-9状态栏</p>
<p>\381. 28-10从云端取个人信息+自增字段</p>
<p>\382. 28-11新建UserInfo表一对一记录用户的社交信息</p>
<p>\383. 28-12用户注册时写入一行记录+点赞收藏时更新数据</p>
<p>\384. 28-13表的写入权限+获取被赞数及被收藏数</p>
<p>\385. 28-14用户登录后显示个人信息</p>
<p>\386. 28-15轻触笔记作者跳转至作者的个人页面</p>
<p>\387. 28-16轻触评论人头像跳至个人页面+#selector的传值</p>
<p>\388. 28-17一个手势识别器只可用于一个view</p>
<p>\389. 28-18用户看自己页面和看别人页面的UI区别</p>
<p>\390. 28-19用户看自己页面和看别人页面的事件区别</p>
<p>\391. 28-20判断何时显示我的草稿cell</p>
<p>\392. 28-21我的草稿cell的UI</p>
<p>\393. 28-22配置我的草稿和我的笔记dataSource</p>
<p>\394. 28-23配置我的草稿和我的笔记layout</p>
<p>\395. 28-24从云端取出我的笔记</p>
<p>\396. 28-25UI微调+复用瀑布流的三种场景</p>
<p>\397. 28-26下拉刷新</p>
<p>\398. 28-27从云端取出我收藏的笔记</p>
<p>\399. 28-28从云端取出我赞过的笔记+点赞优化</p>
<p>\400. 28-29awakeFromNib和dequeueReusableCell的执行顺序</p>
<p>\401. 28-30点击我的草稿cell进入草稿总页面</p>
<p>\402. 28-31跳转优化+bug处理</p>
<hr>
<h5 id="29-编辑资料"><a href="#29-编辑资料" class="headerlink" title="29-编辑资料"></a><strong>29-编辑资料</strong></h5><p>\403. 29-1编辑个人简介UI</p>
<p>\404. 29-2正向传值+限制简介字数</p>
<p>\405. 29-3编辑个人简介</p>
<p>\406. 29-4编辑资料UI分析+静态tableView</p>
<p>\407. 29-5编辑资料UI</p>
<p>\408. 29-6照片视频选择器PHPickerViewController</p>
<p>\409. 29-7获取用户选择的照片</p>
<p>\410. 29-8用代码写view-自定义软键盘inputView+UIPickerView(上)</p>
<p>\411. 29-9用代码写view-自定义软键盘inputView+UIPickerView(下)</p>
<p>\412. 29-10用ActionSheetPicker-3.0做单选picker</p>
<p>\413. 29-11日期选择器</p>
<p>\414. 29-12最小最大日期+代码优化</p>
<p>\415. 29-13复用编辑简介页面+显示个人页传过来的头像昵称和性别</p>
<p>\416. 29-14显示个人页传过来的生日和简介</p>
<p>\417. 29-15编辑资料完成后把数据写入云端+显示到个人页</p>
<hr>
<h5 id="30-个人设置"><a href="#30-个人设置" class="headerlink" title="30-个人设置"></a><strong>30-个人设置</strong></h5><p>\418. 30-1个人设置UI</p>
<p>\419. 30-2计算缓存文件的容量</p>
<p>\420. 30-3用guard进行代码重构+清除缓存</p>
<p>\421. 30-4跳转至AppStore评价页+退出登录+通知设置UI</p>
<p>\422. 30-5账号页UI</p>
<p>\423. 30-6手机号的绑定解绑及换绑</p>
<p>\424. 30-7设置登录密码UI</p>
<p>\425. 30-8动态跳转performSegue</p>
<p>\426. 30-9完成按钮的展示与否+returnKey处理+验证用户输入的密码</p>
<p>\427. 30-10设置或修改登录密码</p>
<p>\428. 30-11手机密码登录UI+验证手机号和密码+限制输入字符数</p>
<p>\429. 30-12手机密码登录+账户锁定</p>
<p>\430. 30-13第三方账号的绑定与解绑</p>
<p>\431. 30-14App深浅色模式切换UI+获取当前App的深浅色模式</p>
<p>\432. 30-15设置App的深浅色模式</p>
<p>\433. 30-16判断当前App是否跟随系统</p>
<p>\434. 30-17跟随系统的深浅色+用户自定义App的深浅色</p>
<hr>
<h5 id="31-推送"><a href="#31-推送" class="headerlink" title="31-推送"></a><strong>31-推送</strong></h5><p>\435. 31-1配置推送</p>
<p>\436. 31-2推送整体流程+获取deviceToken存入Installation表</p>
<p>\437. 31-3配置私钥签名并加密JWT</p>
<p>\438. 31-4请求用户通知权限+获取当前授权状态</p>
<p>\439. 31-5用户拒绝授权时跳转至App设置页+笔记数字段的增减</p>
<p>\440. 31-6全局alert</p>
<p>\441. 31-7个人设置页的通知设置</p>
<p>\442. 31-8从设置App跳转回来后刷新UI</p>
<p>\443. 31-9flag变量的reset+代码优化</p>
<p>\444. 31-10LeanCloud后台在线发送推送</p>
<p>\445. 31-11使用频道动态发送推送+在闭包中显式捕获self</p>
<p>\446. 31-12关联installation对象和用户对象+定向推送</p>
<p>\447. 31-13发布评论bug处理+配置推送环境+从客户端发送推送</p>
<p>\448. 31-14动态设定推送内容+在点击推送后触发的函数中获取payload</p>
<p>\449. 31-15利用payload中自定义的key传值+点击推送跳至相应的笔记页</p>
<p>\450. 31-16点击推送横幅进详情页时的点赞去重</p>
<p>\451. 31-17返回瀑布流页面时的点赞去重</p>
<p>\452. 31-18App进前台时清除角标</p>
<hr>
<h5 id="32-转场动画"><a href="#32-转场动画" class="headerlink" title="32-转场动画"></a><strong>32-转场动画</strong></h5><p>\453. 32-1把系统自带的present和dismiss转场动画改为push和pop动画</p>
<p>\454. 32-2瀑布流和详情页之间的视觉转场动画</p>
<p>\455. 32-3同一个view加同一种手势+用平移手势x轴移动量判断左滑右滑</p>
<p>\456. 32-4从详情页回瀑布流时的交互动画-右滑dismiss</p>
<p>\457. 32-5实时交互动画+平移手势的速度</p>
<p>\458. 32-6从详情页进个人页时的交互动画-左滑跳转</p>
<hr>
<h5 id="33-内测"><a href="#33-内测" class="headerlink" title="33-内测"></a><strong>33-内测</strong></h5><p>\459. 33-1绑定API访问域名和文件访问域名</p>
<p>\460. 33-2Ad Hoc内测-获取设备的UUID并添加设备</p>
<p>\461. 33-3Ad Hoc内测-打包App并上传至蒲公英+获取App的下载地址</p>
<p>\462. 33-4内部版本和外部版本</p>
<p>\463. 33-5发布App的四种方式+发布App至AppStoreConnect</p>
<p>\464. 33-6TestFlight内测-内部测试员</p>
<p>\465. 33-7TestFlight内测-Beta版App审核+外部测试员</p>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="mailto:undefined">Albert Yuan</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="https://yllove.gitee.io/2021/09/02/%E4%BB%BF%E5%B0%8F%E7%BA%A2%E4%B9%A6%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E5%B0%8F%E7%BA%A2%E4%B9%A6%E9%A1%B9%E7%9B%AE%E5%8A%9F%E8%83%BD%E7%9B%AE%E5%BD%95/">https://yllove.gitee.io/2021/09/02/%E4%BB%BF%E5%B0%8F%E7%BA%A2%E4%B9%A6%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E5%B0%8F%E7%BA%A2%E4%B9%A6%E9%A1%B9%E7%9B%AE%E5%8A%9F%E8%83%BD%E7%9B%AE%E5%BD%95/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://yllove.gitee.io" target="_blank">Albert Yuan's Blog</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/blog/tags/Swift/">Swift</a><a class="post-meta__tags" href="/blog/tags/Swift%E9%A1%B9%E7%9B%AE/">Swift项目</a></div><div class="post_share"><div class="social-share" data-image="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbpic.588ku.com%2Felement_origin_min_pic%2F18%2F03%2F22%2F4e2d28d716f1611ad997912eb463ffbe.jpg&amp;refer=http%3A%2F%2Fbpic.588ku.com&amp;app=2002&amp;size=f9999,10000&amp;q=a80&amp;n=0&amp;g=0n&amp;fmt=jpeg?sec=1633152676&amp;t=2f3a092b8df4077187b137d42d5cda66" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/social-share.js/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://fastly.jsdelivr.net/npm/social-share.js/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/blog/2021/08/31/Swift/swift%E7%BA%AF%E4%BB%A3%E7%A0%81%E5%90%AF%E5%8A%A8/"><img class="prev-cover" src= "" data-lazy-src="https://img1.baidu.com/it/u=2474332960,4287768016&amp;fm=26&amp;fmt=auto&amp;gp=0.jpg" onerror="onerror=null;src='/blog/img/defaultCover.gif'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">swift纯代码启动</div></div></a></div><div class="next-post pull-right"><a href="/blog/2021/09/02/Swift/%E4%BD%95%E6%97%B6%E7%94%A8struct%E4%BD%95%E6%97%B6%E7%94%A8class/%E4%BD%95%E6%97%B6%E7%94%A8struct%E4%BD%95%E6%97%B6%E7%94%A8class/"><img class="next-cover" src= "" data-lazy-src="https://img0.baidu.com/it/u=3377328650,417659347&amp;fm=26&amp;fmt=auto&amp;gp=0.jpg" onerror="onerror=null;src='/blog/img/defaultCover.gif'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">何时用struct何时用class?(值类型与引用类型探究)</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span> 相关推荐</span></div><div class="relatedPosts-list"><div><a href="/blog/2021/08/17/RxSwift/RxSwift初识/" title="RxSwift初识"><img class="cover" src= "" data-lazy-src="https://miro.medium.com/max/1400/1*WvSoiQrJV0Bjpau2_s9fmw.jpeg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-08-17</div><div class="title">RxSwift初识</div></div></a></div><div><a href="/blog/2021/09/15/RxSwift/RxSwift的使用详解1/" title="RxSwift的使用详解1"><img class="cover" src= "" data-lazy-src="https://www.hangge.com/blog_uploads/201801/2018010609150332714.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-09-15</div><div class="title">RxSwift的使用详解1</div></div></a></div><div><a href="/blog/2021/09/17/RxSwift/RxSwift的使用详解10-条件和布尔操作符/" title="RxSwift的使用详解10-条件和布尔操作符"><img class="cover" src= "" data-lazy-src="https://www.hangge.com/blog_uploads/201801/2018012419380031551.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-09-17</div><div class="title">RxSwift的使用详解10-条件和布尔操作符</div></div></a></div><div><a href="/blog/2021/09/16/RxSwift/RxSwift的使用详解2-响应式编程与传统编程的比较/" title="RxSwift的使用详解2-响应式编程与传统编程的比较"><img class="cover" src= "" data-lazy-src="https://www.hangge.com/blog_uploads/201801/2018010520271321260.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-09-16</div><div class="title">RxSwift的使用详解2-响应式编程与传统编程的比较</div></div></a></div><div><a href="/blog/2021/09/16/RxSwift/RxSwift的使用详解3-Observable介绍与创建可观察序列/" title="RxSwift的使用详解3-Observable介绍与创建可观察序列"><img class="cover" src= "" data-lazy-src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.51yuansu.com%2Fpic3%2Fcover%2F00%2F90%2F36%2F58dbe747391e4_610.jpg&refer=http%3A%2F%2Fpic.51yuansu.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1634356138&t=248a78e6bca1ed2479d732ae8ef28254" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-09-16</div><div class="title">RxSwift的使用详解3-Observable介绍与创建可观察序列</div></div></a></div><div><a href="/blog/2021/09/16/RxSwift/RxSwift的使用详解4-Observable订阅-事件监听-订阅销毁/" title="RxSwift的使用详解4-Observable订阅-事件监听-订阅销毁"><img class="cover" src= "" data-lazy-src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fnimg.ws.126.net%2F%3Furl%3Dhttp%253A%252F%252Fdingyue.ws.126.net%252F2021%252F0822%252Fc74e238ej00qy8783002cc000m800ekc.jpg%26thumbnail%3D650x2147483647%26quality%3D80%26type%3Djpg&refer=http%3A%2F%2Fnimg.ws.126.net&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1634363191&t=72ca99f133fe4756f19a0c538c073a3e" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-09-16</div><div class="title">RxSwift的使用详解4-Observable订阅-事件监听-订阅销毁</div></div></a></div></div></div><hr/><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i><span> 评论</span></div></div><div class="comment-wrap"><div><div class="vcomment" id="vcomment"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src= "" data-lazy-src="/blog/img/favicon.png" onerror="this.onerror=null;this.src='/blog/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">Albert Yuan</div><div class="author-info__description">博学之,审问之,慎思之,明辨之,笃行之</div></div><div class="card-info-data"><div class="card-info-data-item is-center"><a href="/blog/archives/"><div class="headline">文章</div><div class="length-num">155</div></a></div><div class="card-info-data-item is-center"><a href="/blog/tags/"><div class="headline">标签</div><div class="length-num">56</div></a></div><div class="card-info-data-item is-center"><a href="/blog/categories/"><div class="headline">分类</div><div class="length-num">32</div></a></div></div><a class="button--animated" id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/yuanliangYL"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/yuanliangYL" target="_blank" title="Github"><i class="fab fa-github"></i></a><a class="social-icon" href="mailto:yuanliangios@163.com" target="_blank" title="Email"><i class="fas fa-envelope"></i></a><a class="social-icon" href="qq:1023817403" target="_blank" title="QQ"><i class="fab fa-qq"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn card-announcement-animation"></i><span>公告</span></div><div class="announcement_content">love cat , love life</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-6"><a class="toc-link" href="#1-%E4%BB%BF%E5%B0%8F%E7%BA%A2%E4%B9%A6%E5%AE%9E%E6%88%98%E6%95%99%E7%A8%8B%E7%AE%80%E4%BB%8B"><span class="toc-text">1-仿小红书实战教程简介</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#2-%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6"><span class="toc-text">2-版本控制</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#3-%E9%A1%B9%E7%9B%AE%E6%95%B4%E4%BD%93%E8%AE%BE%E8%AE%A1"><span class="toc-text">3-项目整体设计</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#4-Cocoapods"><span class="toc-text">4-Cocoapods</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#5-%E6%A8%AA%E6%BB%91Tab%E5%B8%83%E5%B1%80"><span class="toc-text">5-横滑Tab布局</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#6-%E7%80%91%E5%B8%83%E6%B5%81%E5%B8%83%E5%B1%80"><span class="toc-text">6-瀑布流布局</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#7-%E6%9C%AC%E5%9C%B0%E5%8C%96%E5%92%8C%E5%9B%BD%E9%99%85%E5%8C%96"><span class="toc-text">7-本地化和国际化</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#8-%E9%80%89%E5%8F%96%E7%85%A7%E7%89%87%E5%92%8C%E8%A7%86%E9%A2%91"><span class="toc-text">8-选取照片和视频</span></a></li></ol></li><li class="toc-item toc-level-5"><a class="toc-link" href="#9-Swift%E9%AB%98%E7%BA%A7"><span class="toc-text">9-Swift高级</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#10-CollectionView"><span class="toc-text">10-CollectionView</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#11-UITextField"><span class="toc-text">11-UITextField</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#12-%E5%8F%82%E4%B8%8E%E8%AF%9D%E9%A2%98%E5%8A%9F%E8%83%BD"><span class="toc-text">12-参与话题功能</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#13-%E9%AB%98%E5%BE%B7%E5%9C%B0%E5%9B%BESDK"><span class="toc-text">13-高德地图SDK</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#14-%E6%9C%AC%E5%9C%B0%E5%AD%98%E5%82%A8CoreData"><span class="toc-text">14-本地存储CoreData</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#15-%E6%9C%AC%E6%9C%BA%E5%8F%B7%E7%A0%81%E4%B8%80%E9%94%AE%E7%99%BB%E5%BD%95"><span class="toc-text">15-本机号码一键登录</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#16-%E6%94%AF%E4%BB%98%E5%AE%9D%E7%99%BB%E5%BD%95"><span class="toc-text">16-支付宝登录</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#17-%E8%8B%B9%E6%9E%9C%E7%99%BB%E5%BD%95"><span class="toc-text">17-苹果登录</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#18-%E6%89%8B%E6%9C%BA%E9%AA%8C%E8%AF%81%E7%A0%81%E7%99%BB%E5%BD%95"><span class="toc-text">18-手机验证码登录</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#19-%E7%99%BB%E5%BD%95%E5%92%8C%E9%80%80%E5%87%BA%E7%99%BB%E5%BD%95"><span class="toc-text">19-登录和退出登录</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#20-%E5%8F%91%E5%B8%83%E7%AC%94%E8%AE%B0%E8%87%B3%E4%BA%91%E7%AB%AF"><span class="toc-text">20-发布笔记至云端</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#21-%E7%AC%94%E8%AE%B0%E8%AF%A6%E6%83%85%E9%A1%B5UI"><span class="toc-text">21-笔记详情页UI</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#22-%E4%BB%8E%E4%BA%91%E7%AB%AF%E5%8F%96%E5%87%BA%E7%AC%94%E8%AE%B0"><span class="toc-text">22-从云端取出笔记</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#23-%E7%82%B9%E8%B5%9E%E5%92%8C%E6%94%B6%E8%97%8F"><span class="toc-text">23-点赞和收藏</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#24-%E7%AC%94%E8%AE%B0%E7%9A%84%E5%88%A0%E9%99%A4%E5%92%8C%E7%BC%96%E8%BE%91"><span class="toc-text">24-笔记的删除和编辑</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#25-%E7%AC%94%E8%AE%B0%E7%9A%84%E8%AF%84%E8%AE%BA"><span class="toc-text">25-笔记的评论</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#26-%E7%AC%94%E8%AE%B0%E8%AF%84%E8%AE%BA%E7%9A%84%E5%9B%9E%E5%A4%8D"><span class="toc-text">26-笔记评论的回复</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#27-%E7%AC%94%E8%AE%B0%E8%AF%A6%E6%83%85%E9%A1%B5%E7%9A%84%E4%BC%98%E5%8C%96%E5%8F%8Abug%E5%A4%84%E7%90%86"><span class="toc-text">27-笔记详情页的优化及bug处理</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#28-%E4%B8%AA%E4%BA%BA%E9%A1%B5%E9%9D%A2"><span class="toc-text">28-个人页面</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#29-%E7%BC%96%E8%BE%91%E8%B5%84%E6%96%99"><span class="toc-text">29-编辑资料</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#30-%E4%B8%AA%E4%BA%BA%E8%AE%BE%E7%BD%AE"><span class="toc-text">30-个人设置</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#31-%E6%8E%A8%E9%80%81"><span class="toc-text">31-推送</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#32-%E8%BD%AC%E5%9C%BA%E5%8A%A8%E7%94%BB"><span class="toc-text">32-转场动画</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#33-%E5%86%85%E6%B5%8B"><span class="toc-text">33-内测</span></a></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/blog/2023/02/07/iOS%E5%BC%80%E5%8F%91%E8%BF%9B%E9%98%B6/iOS-%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BD%91%E9%A1%B5%E4%B8%8B%E8%BD%BDIPA%E5%8C%85/" title="iOS 自定义网页下载IPA包"><img src= "" data-lazy-src="https://img.mp.itc.cn/upload/20170409/1a8f793d7282451cbd1beb6841608c90_th.jpeg" onerror="this.onerror=null;this.src='/blog/img/defaultCover.gif'" alt="iOS 自定义网页下载IPA包"/></a><div class="content"><a class="title" href="/blog/2023/02/07/iOS%E5%BC%80%E5%8F%91%E8%BF%9B%E9%98%B6/iOS-%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BD%91%E9%A1%B5%E4%B8%8B%E8%BD%BDIPA%E5%8C%85/" title="iOS 自定义网页下载IPA包">iOS 自定义网页下载IPA包</a><time datetime="2023-02-07T02:46:29.851Z" title="更新于 2023-02-07 10:46:29">2023-02-07</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2023/02/06/Flutter/Flutter%E6%8E%A5%E5%85%A5%E5%8E%9F%E7%94%9F-iOS/" title="flutter接入原生-iOS"><img src= "" data-lazy-src="https://pic4.zhimg.com/v2-6a115fea4db1ad770dccf4119bfab36f_1440w.jpg?source=172ae18b" onerror="this.onerror=null;this.src='/blog/img/defaultCover.gif'" alt="flutter接入原生-iOS"/></a><div class="content"><a class="title" href="/blog/2023/02/06/Flutter/Flutter%E6%8E%A5%E5%85%A5%E5%8E%9F%E7%94%9F-iOS/" title="flutter接入原生-iOS">flutter接入原生-iOS</a><time datetime="2023-02-07T01:18:53.661Z" title="更新于 2023-02-07 09:18:53">2023-02-07</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2022/12/17/iOS%E5%BC%80%E5%8F%91%E8%BF%9B%E9%98%B6/iOS%20%E5%A6%82%E4%BD%95%E5%9C%A8%E6%A8%A1%E6%8B%9F%E5%99%A8%E4%B8%AD%E5%AE%89%E8%A3%85APP/" title="iOS 如何在模拟器中安装APP"><img src= "" data-lazy-src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fwww.winwin7.com%2Fuploadfile%2F2021%2F0114%2F20210114141748239.jpg&amp;refer=http%3A%2F%2Fwww.winwin7.com&amp;app=2002&amp;size=f9999,10000&amp;q=a80&amp;n=0&amp;g=0n&amp;fmt=auto?sec=1673854539&amp;t=aad2108ffb799b04e94a28cc58f038f1" onerror="this.onerror=null;this.src='/blog/img/defaultCover.gif'" alt="iOS 如何在模拟器中安装APP"/></a><div class="content"><a class="title" href="/blog/2022/12/17/iOS%E5%BC%80%E5%8F%91%E8%BF%9B%E9%98%B6/iOS%20%E5%A6%82%E4%BD%95%E5%9C%A8%E6%A8%A1%E6%8B%9F%E5%99%A8%E4%B8%AD%E5%AE%89%E8%A3%85APP/" title="iOS 如何在模拟器中安装APP">iOS 如何在模拟器中安装APP</a><time datetime="2022-12-17T07:48:56.594Z" title="更新于 2022-12-17 15:48:56">2022-12-17</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2021/08/05/Swift/swift%E5%B8%B8%E7%94%A8%E4%B8%89%E6%96%B9%E5%BA%93/" title="swift常用三方库"><img src= "" data-lazy-src="https://photos.infinum.com/store/b558bd40787ecad225d9c66322f14522" onerror="this.onerror=null;this.src='/blog/img/defaultCover.gif'" alt="swift常用三方库"/></a><div class="content"><a class="title" href="/blog/2021/08/05/Swift/swift%E5%B8%B8%E7%94%A8%E4%B8%89%E6%96%B9%E5%BA%93/" title="swift常用三方库">swift常用三方库</a><time datetime="2022-12-16T06:37:20.115Z" title="更新于 2022-12-16 14:37:20">2022-12-16</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2022/12/12/iOS%E5%BC%80%E5%8F%91%E8%BF%9B%E9%98%B6/GCD%E8%BF%9B%E9%98%B6%E4%B9%8BDispatchWorkItem%E5%92%8CDispatchGroup/" title="GCD进阶之DispatchWorkItem和DispatchGroup"><img src= "" data-lazy-src="/blog/img/defaultCover.png" onerror="this.onerror=null;this.src='/blog/img/defaultCover.gif'" alt="GCD进阶之DispatchWorkItem和DispatchGroup"/></a><div class="content"><a class="title" href="/blog/2022/12/12/iOS%E5%BC%80%E5%8F%91%E8%BF%9B%E9%98%B6/GCD%E8%BF%9B%E9%98%B6%E4%B9%8BDispatchWorkItem%E5%92%8CDispatchGroup/" title="GCD进阶之DispatchWorkItem和DispatchGroup">GCD进阶之DispatchWorkItem和DispatchGroup</a><time datetime="2022-12-12T07:19:37.277Z" title="更新于 2022-12-12 15:19:37">2022-12-12</time></div></div></div></div></div></div></main><footer id="footer" style="background-image: url('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbpic.588ku.com%2Felement_origin_min_pic%2F18%2F03%2F22%2F4e2d28d716f1611ad997912eb463ffbe.jpg&amp;refer=http%3A%2F%2Fbpic.588ku.com&amp;app=2002&amp;size=f9999,10000&amp;q=a80&amp;n=0&amp;g=0n&amp;fmt=jpeg?sec=1633152676&amp;t=2f3a092b8df4077187b137d42d5cda66')"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2023 By Albert Yuan</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div><div class="footer_custom_text">Hi, welcom to my  blog</div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="font-plus" type="button" title="放大字体"><i class="fas fa-plus"></i></button><button id="font-minus" type="button" title="缩小字体"><i class="fas fa-minus"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><a id="to_comment" href="#post-comment" title="直达评论"><i class="fas fa-comments"></i></a><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div id="algolia-search"><div class="search-dialog"><div class="search-dialog__title" id="algolia-search-title">Algolia</div><div id="algolia-input-panel"><div id="algolia-search-input"></div></div><hr/><div id="algolia-search-results"><div id="algolia-hits"></div><div id="algolia-pagination"></div><div id="algolia-stats"></div></div><span class="search-close-button"><i class="fas fa-times"></i></span></div><div id="search-mask"></div></div><div><script src="/blog/js/utils.js"></script><script src="/blog/js/main.js"></script><script src="https://fastly.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js"></script><script src="/blog/js/search/algolia.js"></script><script>var preloader = {
  endLoading: () => {
    document.body.style.overflow = 'auto';
    document.getElementById('loading-box').classList.add("loaded")
  },
  initLoading: () => {
    document.body.style.overflow = '';
    document.getElementById('loading-box').classList.remove("loaded")

  }
}
window.addEventListener('load',preloader.endLoading())</script><div class="js-pjax"><script>if (!window.MathJax) {
  window.MathJax = {
    tex: {
      inlineMath: [ ['$','$'], ["\\(","\\)"]],
      tags: 'ams'
    },
    chtml: {
      scale: 1.2
    },
    options: {
      renderActions: {
        findScript: [10, doc => {
          for (const node of document.querySelectorAll('script[type^="math/tex"]')) {
            const display = !!node.type.match(/; *mode=display/)
            const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display)
            const text = document.createTextNode('')
            node.parentNode.replaceChild(text, node)
            math.start = {node: text, delim: '', n: 0}
            math.end = {node: text, delim: '', n: 0}
            doc.math.push(math)
          }
        }, ''],
        insertScript: [200, () => {
          document.querySelectorAll('mjx-container:not\([display]\)').forEach(node => {
            const target = node.parentNode
            if (target.nodeName.toLowerCase() === 'li') {
              target.parentNode.classList.add('has-jax')
            } else {
              target.classList.add('has-jax')
            }
          });
        }, '', false]
      }
    }
  }
  
  const script = document.createElement('script')
  script.src = 'https://fastly.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js'
  script.id = 'MathJax-script'
  script.async = true
  document.head.appendChild(script)
} else {
  MathJax.startup.document.state(0)
  MathJax.texReset()
  MathJax.typeset()
}</script><script>function loadValine () {
  function initValine () {
    const valine = new Valine(Object.assign({
      el: '#vcomment',
      appId: 'REc8eytE1gJDl3d8FkudLNlL-gzGzoHsz',
      appKey: 'gGO3y8I9oVlc4Cd5N1fizNPW',
      avatar: 'monsterid',
      serverURLs: '',
      emojiMaps: "",
      path: window.location.pathname,
      visitor: false
    }, null))
  }

  if (typeof Valine === 'function') initValine() 
  else getScript('https://fastly.jsdelivr.net/npm/valine/dist/Valine.min.js').then(initValine)
}

if ('Valine' === 'Valine' || !true) {
  if (true) btf.loadComment(document.getElementById('vcomment'),loadValine)
  else setTimeout(loadValine, 0)
} else {
  function loadOtherComment () {
    loadValine()
  }
}</script></div><script defer="defer" id="fluttering_ribbon" mobile="true" src="https://fastly.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-fluttering-ribbon.min.js"></script><script id="canvas_nest" defer="defer" color="255,0,0" opacity="0.7" zIndex="-1" count="99" mobile="false" src="https://fastly.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-nest.min.js"></script><script src="https://fastly.jsdelivr.net/npm/butterfly-extsrc@1/dist/activate-power-mode.min.js"></script><script>POWERMODE.colorful = true;
POWERMODE.shake = true;
POWERMODE.mobile = true;
document.body.addEventListener('input', POWERMODE);
</script><script id="click-heart" src="https://fastly.jsdelivr.net/npm/butterfly-extsrc@1/dist/click-heart.min.js" async="async" mobile="false"></script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>